#include "TokenKinds.h"
#include "CharInfo.h"

#include <unordered_map>


namespace cal
{

using namespace std;
using namespace tok;

static const char* const TokNames[] = {
#define TOK(X) #X,
#define KEYWORD(X, Y) #X,
#include "TokenKinds.def"
    nullptr
};

static const unordered_map<std::string, TokenKind> KeyWord_Kinds {
#define KEYWORD(X, Y) { #X, tok::kw_ ## X },
#include "TokenKinds.def"
};

std::string get_token_name(TokenKind kind)
{
    if (kind < tok::NUM_TOKENS)
        return TokNames[kind];
    return "";
}

std::string get_keyword_spelling(TokenKind kind) 
{
    switch (kind) {
#define KEYWORD(X, Y) case kw_ ## X: return #X;
#include "TokenKinds.def"
    default: break;
    }
    return "";
}

std::string get_keyword_syntax(TokenKind kind)
{
    switch (kind) {
#define KEYWORD(X, Y) case kw_ ## X: return Y;
#include "TokenKinds.def"
    default: break;
    }
    return "";
}

std::string get_keyword_syntax(const std::string& keyword)
{
    TokenKind kind = get_keyword_tokenkind(keyword);
    if (kind == tok::unknown) return "";
    return get_keyword_syntax(kind);
}

TokenKind get_keyword_tokenkind(const std::string& keyword)
{
    if (KeyWord_Kinds.count(keyword)) 
        return KeyWord_Kinds.at(keyword);
    return tok::unknown;
}

char get_operator_spelling(TokenKind kind) 
{
    switch (kind) {
#define OPERATOR(X, Y) case X: return Y;
#include "TokenKinds.def"
    default: break;
    }
    return 0;
}

std::string get_operator_spelling_str(tok::TokenKind kind)
{
    char c = get_operator_spelling(kind);
    if (c == 0) return ""; 
    return get_literal_string(c);
}

TokenKind get_opeartor_tokenkind(char c)
{
    switch (c) {
#define OPERATOR(X, Y) case Y: return X;
#include "TokenKinds.def"
    default: break;
    }
    return tok::unknown;
}

}   // namespace cal
